
package com.niguang.common.util;

import com.alibaba.fastjson.JSON;
import com.niguang.common.pojo.ImageRes;
import com.sun.jersey.core.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * HttpClientUtil
 *
 * @author
 */
@Slf4j
public class HttpClientUtil {

    private static final String CHARSET_UTF_8 = "UTF-8";

    private static final String CONTENT_TYPE_JSON = "application/json";

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    private static String UPLOAD = "http://47.106.194.24:9333/submit";
    private static String SELECT = "http://file.gzhuijiangyuan.com";


    private static void doHttpClientClose(CloseableHttpClient httpClient) {
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送get请求
     *
     * @param url
     * @return
     */
    public static String get(String url) {
        String res = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            URL url1 = null;
            try {
                url1 = new URL(url);
                URI uri = new URI(url1.getProtocol(), url1.getHost(), url1.getPath(), url1.getQuery(), null);
                HttpGet httpGet = new HttpGet(uri);
                httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
                res = execute(httpClient, httpGet);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }

    public static String get(String url, String cookie) {
        String res = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            URL url1 = null;
            try {
                url1 = new URL(url);
                URI uri = new URI(url1.getProtocol(), url1.getHost(), url1.getPath(), url1.getQuery(), null);
                HttpGet httpGet = new HttpGet(uri);
                httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
                httpGet.setHeader("Cookie", cookie);
                res = execute(httpClient, httpGet);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }

    public static String getByHeaderCity(String url, String city) {
        String res = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            URL url1 = null;
            try {
                url1 = new URL(url);
                URI uri = new URI(url1.getProtocol(), url1.getHost(), url1.getPath(), url1.getQuery(), null);
                HttpGet httpGet = new HttpGet(uri);
                httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
                httpGet.setHeader("city", city);
                res = execute(httpClient, httpGet);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }


    /**
     * 发送post请求
     *
     * @param url    post url
     * @param params post参数
     * @return
     */
    public static String post(String url, Map<String, String> params) {
        String res = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpPost httpPost = httpPostHandler(url, params);
            res = execute(httpClient, httpPost);
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }

    /**
     * 发送delete请求
     *
     * @param url 请求地址
     *            返回数据编码
     * @return String
     */
    public static String sndDelete(String url) {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpDelete del = new HttpDelete(url);
        try {
            // 提交请求并以指定编码获取返回数据
            HttpResponse httpResponse = httpClient.execute(del);
            logger.info("请求地址：" + url + "；响应状态：" + httpResponse.getStatusLine());
            HttpEntity entity = httpResponse.getEntity();
            return EntityUtils.toString(entity, CHARSET_UTF_8);
        } catch (ClientProtocolException e) {
            logger.error("协议异常,堆栈信息如下", e);
        } catch (IOException e) {
            logger.error("网络异常,堆栈信息如下", e);
        } finally {
            // 关闭连接，释放资源
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
                httpClient = null;
            }
        }
        return null;
    }

    /**
     * post json数据
     *
     * @param url
     * @param jsonStr
     * @return
     */
    public static String postJson(String url, String jsonStr) {
        String res = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity stringEntity;
            try {
                stringEntity = new StringEntity(jsonStr);
            } catch (UnsupportedEncodingException e) {
                return null;
            }
            httpPost.setHeader("Content-Type", CONTENT_TYPE_JSON);
            httpPost.setEntity(stringEntity);
            res = execute(httpClient, httpPost);
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }

    /**
     * 文件上传
     *
     * @param ttl        图片在小文件服务器上存活时间 eg:
     *                   3m: 3 minutes
     *                   4h: 4 hours
     *                   5d: 5 days
     *                   6w: 6 weeks
     *                   7M: 7 months
     *                   8y: 8 years
     * @param collection
     * @return
     */
    public static String uploadFile(MultipartFile multipartFile, String ttl, String collection) {
        try {
            String contentType = multipartFile.getContentType();
            ContentType mimeType = ContentType.getByMimeType(contentType);
            if (mimeType == null) {
                mimeType = ContentType.create(contentType, "UTF-8");
            }
            String originalFilename = multipartFile.getOriginalFilename();
            String url = UPLOAD;
            if (StringUtils.isNotBlank(ttl) && StringUtils.isNotBlank(collection)) {
                url = UPLOAD + "?ttl=" + ttl + "&collection=" + collection;
            } else if (StringUtils.isNotBlank(ttl)) {
                url = UPLOAD + "?ttl=" + ttl;
            } else if (StringUtils.isNotBlank(collection)) {
                url = UPLOAD + "?collection=" + collection;
            }
            return Request.Post(url).body(
                    MultipartEntityBuilder.create()
                            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                            .setCharset(Charset.forName("UTF-8"))
                            .addBinaryBody("file", multipartFile.getBytes(), mimeType, originalFilename)
                            .build()
            ).execute()
                    .returnContent()
                    .asString(Charset.forName("UTF-8"));
        } catch (Exception e) {
            log.error("上传文件出错,文件名：{},ttl:{}", multipartFile.getOriginalFilename(), ttl, e);
        }
        return "";
    }

    /**
     * 上传图片到服务器
     *
     * @param file
     * @param ttl        存活时间
     * @param collection 集合
     * @return
     * @see HttpClientUtil#uploadFile
     */
    public static String uploadImage(Object file, String ttl, String collection) {
        String s = null;
        if (file instanceof MultipartFile) {
            s = uploadFile((MultipartFile) file, ttl, collection);
        } else if (file instanceof String) {
            s = uploadBase64((String) file, ttl, collection);
        } else {
            return null;
        }
        if (StringUtils.isBlank(s)) {
            return null;
        }
        ImageRes imageRes = JSON.parseObject(s, ImageRes.class);
        String fid = imageRes.getFid();
        String fileName = imageRes.getFileName();
        Integer size = imageRes.getSize();
        String fileUrl = imageRes.getFileUrl();
        if (StringUtils.isBlank(fid) || StringUtils.isBlank(fileName) || size == null || size == 0 || StringUtils.isBlank(fileUrl)) {
            log.error("上传文件出错，文件名：{}", fileName);
            return null;
        }
        return SELECT + fileUrl;
    }


    public static String uploadBase64(String base64, String ttl, String collection) {
        try {
            String originalFilename = getFileName() + ".jpg";
            byte[] b = Base64.decode(base64);
            String url = UPLOAD;
            if (StringUtils.isNotBlank(ttl) && StringUtils.isNotBlank(collection)) {
                url = UPLOAD + "?ttl=" + ttl + "&collection=" + collection;
            } else if (StringUtils.isNotBlank(ttl)) {
                url = UPLOAD + "?ttl=" + ttl;
            } else if (StringUtils.isNotBlank(collection)) {
                url = UPLOAD + "?collection=" + collection;
            }
            return Request.Post(url).body(
                    MultipartEntityBuilder.create()
                            .setCharset(Charset.forName("UTF-8"))
                            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                            .addBinaryBody("file", b, ContentType.MULTIPART_FORM_DATA, originalFilename)
                            .build()
            ).execute()
                    .returnContent()
                    .asString(Charset.forName("UTF-8"));
        } catch (Exception e) {
            log.error("BASE64位流上传文件出错,ttl:{}", ttl, e);
        }
        return "";
    }

    private static String getFileName() {
        LocalDateTime nowTime = LocalDateTime.now();
        int year = nowTime.getYear();
        int monthValue = nowTime.getMonthValue();
        int day = nowTime.getDayOfMonth();
        int hour = nowTime.getHour();
        int minute = nowTime.getMinute();
        int second = nowTime.getSecond();
        String time = year + "" + monthValue + "" + day + "" + hour + "" + minute + "" + second + "" + System.currentTimeMillis();
        return time;
    }

    private static String[] changeFid(String fileName, String fid) {
        String[] gather = new String[2];
        if (fileName.contains(".")) {
            gather[0] = fileName.substring(fileName.lastIndexOf(".") + 1);
            gather[1] = fid.replace(",", "/") + "." + gather[0];
            return gather;
        }
        gather[0] = null;
        gather[1] = fid.replace(",", "/");
        return gather;
    }


    private static HttpPost httpPostHandler(String url, Map<String, String> params) {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, CHARSET_UTF_8));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return httpPost;
    }

    private static String execute(CloseableHttpClient httpClient, HttpUriRequest httpGetOrPost) {
        String res = null;
        int statusCode = 0;
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGetOrPost);
            HttpEntity entity = response.getEntity();
            statusCode = response.getStatusLine().getStatusCode();
            res = EntityUtils.toString(entity, CHARSET_UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            doResponseClose(response);
        }

        if (statusCode == HttpStatus.OK.value()) {
            return res;
        } else {
            log.error("http请求失败!状态码为:{},返回结果为:{}", statusCode, res);
            return null;
        }
    }

    private static void doResponseClose(CloseableHttpResponse response) {
        if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static String sendPost(String url, String param) {
        DataOutputStream out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new DataOutputStream(conn.getOutputStream());
            // 发送请求参数
            out.write(param.getBytes(StandardCharsets.UTF_8));
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String lines;
            StringBuffer sb = new StringBuffer();
            while ((lines = in.readLine()) != null) {
                lines = new String(lines.getBytes());
                sb.append(lines);
            }
            result = sb.toString();
        } catch (Exception e) {
            log.error("发送 POST 请求出现异常！", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                log.error("发送 POST 请求出现异常！", ex);
            }
        }
        return result;
    }


    // public static void main(String[] args) {
    // String res = get("http://www.cnbeta.com/articles/455121.htm");
    // System.out.println(res);
    // }

}
